<template>
    <div class="main">
        <el-form :inline="true" :model="formData" ref="formRef">
            <el-form-item label="姓名" prop="name" :label-width="60">
                <el-input v-model="formData.name" placeholder="请输入会员姓名" />
            </el-form-item>
            <el-form-item label="手机号" prop="phone" :label-width="60">
                <el-input v-model="formData.phone" placeholder="请输入会员手机号" />
            </el-form-item>
            <el-form-item label="邮箱" prop="email" :label-width="60">
                <el-input v-model="formData.email" placeholder="请输入会员邮箱" />
            </el-form-item>
            <el-form-item label="关键字" prop="keyword" :label-width="60">
                <el-input v-model="formData.keyword" placeholder="请输入会员关键字" />
            </el-form-item>

            <el-form-item>
                <el-button type="primary" @click="resetForm">
                    <el-icon>
                        <Refresh />
                    </el-icon>
                    &nbsp;重置
                </el-button>
            </el-form-item>
        </el-form>

        <!-- 按钮区 -->
        <div class="action">
            <el-button type="success" @click="newMember()">新增</el-button>
            <el-button type="success" @click="editMember()">修改</el-button>
            <el-button type="success" @click="findByForm()">查询</el-button>
            <el-button type="danger" @click="deleteAll()">删除</el-button>
        </div>

        <!-- 表格区域 -->
        <el-table class="datagrid" :data="members" :stripe="true" :border="true" :highlight-current-row="true"
            @row-click="rowClick" style="width: 100%" ref="datagridRef">
            <el-table-column type="selection" width="55" align="center" />
            <el-table-column prop="id" label="ID" width="80" fixed="left" />
            <el-table-column prop="name" label="姓名" width="150" fixed="left" />
            <el-table-column prop="pinyin" label="拼音" width="150" fixed="left" />
            <el-table-column prop="phone" label="手机号" width="180" fixed="left" />
            <el-table-column prop="sex" label="性别" width="60" />
            <el-table-column prop="email" label="邮箱" width="240" />
            <el-table-column prop="qq" label="QQ" width="180" />
            <el-table-column prop="wechat" label="微信" width="220" />
            <el-table-column prop="birthday" label="出生日期" width="180" />
            <el-table-column prop="cardId" label="身份证号" width="180" />
            <el-table-column prop="description" label="备注" />
            <el-table-column prop="createTime" label="创建时间" width="180" />

            <el-table-column label="操作" fixed="right" width="180" align="center">
                <template #default="scope">
                    <el-button size="small" type="success" @click="editSingle(scope.row)">
                        <el-icon>
                            <Edit />
                        </el-icon>&nbsp;编辑
                    </el-button>
                    <el-button size="small" type="danger" @click="deleteSingle(scope.row)">
                        <el-icon>
                            <Delete />
                        </el-icon>&nbsp;删除
                    </el-button>
                </template>
            </el-table-column>
        </el-table>

        <!-- 分页条中的页面大小必须和查询函数中的页面大小匹配，否则会出现多次查询 -->
        <el-pagination class="page" v-model:current-page="pi.page" v-model:page-size="pi.limit" :total="pi.total"
            :page-sizes="[10, 20, 50, 100]" :background="true" layout="total, sizes, prev, pager, next, jumper"
            @change="change" />
    </div>

    <!-- 弹出新增或修改对话框 -->
    <el-dialog :title="dialogTitle" width="600px" v-model="dialogShow" :draggable="true" :close-on-click-modal="false"
        @close="clearDialog()">
        <div>
            <el-form ref="memberForm" label-width="100" :model="memberData" :rules="rules">
                <el-row>
                    <el-col :span="12">
                        <el-form-item label="姓名：" prop="name">
                            <el-input v-model="memberData.name" placeholder="会员姓名"></el-input>
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="拼音：" prop="pinyin">
                            <el-input v-model="memberData.pinyin" placeholder="会员姓名拼音"></el-input>
                        </el-form-item>
                    </el-col>
                </el-row>

                <el-row>
                    <el-col :span="12">
                        <el-form-item label="性别：" prop="sex">
                            <el-radio-group v-model="memberData.sex">
                                <el-radio value="男">男</el-radio>
                                <el-radio value="女">女</el-radio>
                            </el-radio-group>
                        </el-form-item>
                    </el-col>

                    <el-col :span="12">
                        <el-form-item label="出生日期：" prop="birthday">
                            <el-date-picker v-model="memberData.birthday" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
                                type="date" placeholder="会员出生日期"></el-date-picker>
                        </el-form-item>
                    </el-col>
                </el-row>

                <el-row>
                    <el-col :span="12">
                        <el-form-item label="电子邮箱：" prop="email" required>
                            <el-input v-model="memberData.email" placeholder="会员电子邮箱"></el-input>
                        </el-form-item>
                    </el-col>

                    <el-col :span="12">
                        <el-form-item label="手机号：" prop="phone" required>
                            <el-input v-model="memberData.phone" placeholder="会员手机号"></el-input>
                        </el-form-item>
                    </el-col>

                    <el-col :span="12">
                        <el-form-item label="QQ：" prop="qq">
                            <el-input v-model="memberData.qq" placeholder="会员QQ号"></el-input>
                        </el-form-item>
                    </el-col>

                    <el-col :span="12">
                        <el-form-item label="微信：" prop="wechat">
                            <el-input v-model="memberData.wechat" placeholder="会员微信号"></el-input>
                        </el-form-item>
                    </el-col>

                    <el-col :span="12">
                        <el-form-item label="身份证号：" prop="cardId">
                            <el-input v-model="memberData.cardId" placeholder="会员身份证号"></el-input>
                        </el-form-item>
                    </el-col>

                    <el-col :span="24">
                        <el-form-item label="备注：" prop="description">
                            <el-input v-model="memberData.description" type="textarea" placeholder="会员备注"></el-input>
                        </el-form-item>
                    </el-col>
                </el-row>

            </el-form>
        </div>
        <template #footer>
            <div class="footer">
                <el-button type="primary" @click="submitMember()">确定</el-button>
                <el-button @click="dialogShow = false">取消</el-button>
            </div>
        </template>
    </el-dialog>
</template>

<style scoped>
.main {
    height: 100%;
    padding: 8px;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
}

.page {
    margin-top: 10px;
}

.datagrid {
    margin-top: 10px;
}
</style>

<script setup>
import { findAll as apiFindAll, deleteByIds as apiDeleteByIds, save as apiSave, update as apiUpdate } from '@/api/MemberApi';
import { reactive, ref, onMounted, toRaw, nextTick } from 'vue';
import { ElMessageBox, ElMessage } from 'element-plus'

// 所有会员
let members = ref([]);

// 分页信息
let pi = reactive({
    page: 1,
    limit: 10,
    total: 0
});

onMounted(async () => {
    findAll();
});


// 查询全部会员
async function findAll(params, page = 1, limit = 10) {
    let result = await apiFindAll(params, page, limit);

    if (result.success) {
        let data = result.data;
        members.value = data.members;
        pi.page = data.page;
        pi.limit = data.limit;
        pi.total = data.total;
    } else {
        pi.total = 0;
    }
}

// 页码改变时触发
async function change(page, limit) {
    await findByForm(page, limit);
}

// 根据表单条件进行查询
async function findByForm(page = 1, limit = 10) {
    let params = toRaw(formData);
    await findAll(params, page, limit);
}

let formRef;
// 重置查询表单
function resetForm() {
    formRef.resetFields();
}

// 查询表单双向绑定数据
let formData = reactive({
    name: "",
    phone: "",
    email: "",
    keyword: ""
});

let datagridRef;
// 表格行点击事件，参数row为一行数据
function rowClick(row) {
    datagridRef.toggleRowSelection(row);
    datagridRef.setCurrentRow(row);
}

// 批量删除全部
async function deleteAll() {
    let selected = datagridRef.getSelectionRows();
    let ids = selected.map(t => t.id);

    await deleteByIds(ids);
}

async function deleteByIds(ids) {
    if (ids.length === 0) {
        ElMessage({
            message: "请选择您要删除的行",
            type: "warning"
        });
    } else {
        ElMessageBox.confirm("是否确认删除选中的行?", "警告", {
            type: "warning"
        }).then(async () => {
            let result = await apiDeleteByIds(ids);
            if (result.success && result.data) {
                ElMessage({
                    type: "success",
                    message: "操作成功，共删除" + result.data + "行"
                });
                findAll();//重新加载
            } else {
                ElMessage({
                    type: "error",
                    message: "操作失败"
                });
            }
        }).catch(error => { });
    }
}

//删除单行
async function deleteSingle(row) {
    await deleteByIds([row.id]);
}

let dialogTitle = ref();
let dialogShow = ref(false);
let memberForm;

// 添加或修改会员的表单数据
let memberData = ref({
    name: "",
    pinyin: "",
    phone: "",
    sex: "男",
    birthday: "",
    email: "",
    qq: "",
    wechat: "",
    description: ""
});


// 表单验证规则
const rules = {
    email: [{
        required: true, message: "邮箱不可为空"
    }],
    phone: [{
        required: true, message: "手机号不可为空"
    }]
};

//添加会员
function newMember() {
    dialogTitle.value = "新增会员";
    dialogShow.value = true;
}

//清空对话框
function clearDialog() {
    memberForm.resetFields();//清空表单内容
}

//提交新增会员或修改会员
async function submitMember() {
    let member = toRaw(memberData.value);

    let result;
    if (member.id) {//有id则为修改，无id则为新增
        result = await apiUpdate(member);
    } else {
        result = await apiSave(member);
    }

    if (result.success) {
        ElMessage({
            type: "success",
            message: member.id ? "修改会员成功" : "新增会员成功"
        });
        dialogShow.value = false;//关闭窗口
        findAll();
    } else {
        ElMessage({
            type: "error",
            message: result.msg || "操作失败"
        });
    }
}

// 修改会员
function editMember() {
    let selected = datagridRef.getSelectionRows();
    if (selected.length === 0) {
        ElMessage({
            type: "error",
            message: "你选中您要修改的行"
        });
    } else if (selected.length > 1) {
        ElMessage({
            type: "error",
            message: "您一次只能修改一行"
        });
    } else {
        let row = toRaw(selected[0]);
        editMemberForRow(row);
    }
}

// 打开修改会员窗口
async function editMemberForRow(row) {
    dialogTitle.value = "修改会员"
    dialogShow.value = true;

    //memberData必须在nextTick中赋值，否则会造成赋值在前，创建dom在后，进而导致表单的重置状态设定为表单首次赋值后（即memberData赋值）的状态
    //https://blog.csdn.net/YSQ_qsy/article/details/126181740
    //nextTick表示在下一个时间滴答中再进行操作（即在渲染完dom之后），有了重置状态之后，再对memberData赋值
    nextTick(() => {
        //注意：Object.assign是浅拷贝，好在memberData也只有一级属性。详见：https://blog.csdn.net/qq_25775675/article/details/126257648
        //如果需要深拷贝，可以参考jQuery的$.extend(true,target,...sources);
        memberData.value = Object.assign({}, row);

        //另一种折衷的方法是做如下操作，虽然可行，但不优雅，在连续序列化和反序列后，可能会导致数据显示格式不一致的情况
        //memberData.value = JSON.parse(JSON.stringify(row));

        //使用以下这种方式是不行的，以下操作会导致，当更改memberData的时候，表格中的数据也会同步修改。
        //比如调用表单的resetFields方法的时候，会响应式的修改memberData中的内容，进而同步修改表中特定行数据的内容。
        //toRaw函数，虽然可以获取响应式对象中的原始对象，但并不能改变原始对象是引用类型，且可能已被监听的事实，
        //可通过watch函数测试当memberData改变时，row是否被同步改变。
        //memberData.value = toRaw(row);

        /* watch(row, (r) => {
            console.log(r);
        }); */
    });
}

// 单行修改会员
function editSingle(row) {
    editMemberForRow(toRaw(row));
}
</script>